#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<ctype.h>

#define kMaxStrLen 10        /* 最大字符串长度 */
#define kMinStrLen 3         /* 最小字符串长度 */
#define kCharBit 5           /* 每个字符占的位数 */
#define kMaxTableSize 500009 /* 散列表最大规模 */

typedef enum { false, true } bool;

/* 文件的词汇索引表 */
typedef struct WordNode *WordList;
struct WordNode {
    int word_pos; /* 单词在散列表中的位置 */
    WordList next; /* 文件中的下一个单词 */
};

WordList InitFileWordList(int n_file) {
    /* 初始化文件的词汇表 */
    WordList file;

    file = (WordList)malloc(sizeof(struct WordNode) * n_file);
    /* 初始化头结点*/
    while (n_file > 0) {
        file[--n_file].word_pos = 0; /* 头结点中存储词汇量 */
        file[n_file].next = NULL;
    }

    return file;
}

/* 倒排索引表 */
typedef struct FileNode *PostingList;
struct FileNode {
    int file_no;
    PostingList next;
};

/* 散列表相关定义与操作 */
typedef long long HashVal; /* 默认散列值为int型 */
typedef HashVal Position; /* 数组下标是元素的位置 */
typedef char ElemSet[kMaxStrLen + 1]; /* 默认数据类型是字符串 */

typedef struct RecordNode *Records;
struct RecordNode {
    ElemSet key; /* 关键字，即单词 */
    int last_file; /* 最后插入的单词所属的文件编号 */
    PostingList pl; /* 倒排索引表 */
};

typedef struct HashNode *HashTable;
struct HashNode {
    Records *ht; /* 散列表数据 */
    int size; /* 散列表当前数据元素个数 */
    int table_size; /* 散列表表长 */
};

HashTable InitHashTable(int table_size) {
    HashTable htable;
    int i;

    htable = (HashTable)malloc(sizeof(struct HashNode));
    htable->ht = (Records *)malloc(sizeof(Records) * table_size);
    for (i = 0; i < table_size; i++) {
        htable->ht[i] = (Records)malloc(sizeof(struct RecordNode));
        htable->ht[i]->last_file = 0; /* 表示该单词对应的倒排表为空 */
        htable->ht[i]->pl = NULL;
    }
    htable->table_size = table_size;
    htable->size = 0;

    return htable;
}

HashVal Hash(ElemSet key, int table_size) {
    HashVal hash_v;
    int i;

    hash_v = 0;
    i = 0;
    while (key[i] != '\0') {
        hash_v = (hash_v << 5) + (key[i] - 'a');
        i++;
    }
    return hash_v % table_size;
}

Position SearchHash(HashTable htable, ElemSet key) {
    /* 找到key的位置，或者是适合插入key的位置 */
    HashVal hash_v;
    Position p;
    int count;

    hash_v = Hash(key, htable->table_size); /* 求得散列地址 */
    p = hash_v;
    count = 0; /* 记录冲突次数 */
    while (htable->ht[p]->last_file != 0 && strcmp(key, htable->ht[p]->key) != 0) {
        count++; /* 记录1次冲突 */
        p ++; /* 线性探测求下一探查地址 */
        if (p >= htable->table_size) {
            p %= htable->table_size;
        }
    }
    return p; /* 这时 htable.ht[p]->key=key或 htable.ht[p]为空 */
}

#define NIL -1 /* 插入不成功的标识 */
Position InsertHash(HashTable htable, ElemSet key, int file_no) {
    /* 将key插入散列表，同时插入对应的倒排索引表 */
    /* 如果插入成功，返回插入的位置；若不成功，返回NIL */
    Position p;
    PostingList f;

    p = SearchHash(htable,
                   key); /* 找到key的位置，或者是适合插入key的位置 */
    if (htable->ht[p]->last_file != file_no) { /* 单词来自新文件 */
        if (htable->ht[p]->last_file == 0) { /* 是新增单词 */
            strcpy(htable->ht[p]->key, key);
        }
        htable->ht[p]->last_file = file_no; /* 更新最后插入的文件编号 */
        /* 将文件编号插入倒排索引表 */
        f = (PostingList)malloc(sizeof(struct FileNode));
        f->file_no = file_no;
        f->next = htable->ht[p]->pl;
        htable->ht[p]->pl = f;
        htable->size++;
    } else { /* 否则是同一文件的重复单词，不插入 */
        p = NIL;
    }
    return p;
}
/* 散列表相关定义与操作 结束 */

bool GetWord(ElemSet word) {
    /* 从当前字符开始，读到单词尾的第1个非字母符号为止 */
    /* 读成功则返回true；读到文件结束则返回false */
    char c;
    int p = 0;

    scanf("%c", &c);
    while (isalpha(c) == 0 && (c != '#')) {
        scanf("%c", &c); /* 跳过开始的非字母 */
    }
    if (c == '#') {
        return false; /* 没读到单词 */
    }
    while (isalpha(c) > 0 && (p < kMaxStrLen)) { /* 读入单词 */
        word[p++] = tolower(c);
        scanf("%c", &c);
    }
    while (isalpha(c) > 0) {
        scanf("%c", &c); /* 跳过超长的字母 */
    }
    if (p < kMinStrLen) {
        return GetWord(word); /* 太短的单词不要，读下一个 */
    } else {
        word[p] = '\0';
        return true; /* 成功返回 */
    }
}

void InsertWordToFile(WordList file, int file_no, int word_pos) {
    /* 将单词在散列表中的位置word_pos存入编号为file_no的文件对应的词汇表 */
    WordList word;

    if (word_pos != NIL) { /* 插入词汇表 */
        word = (WordList)malloc(sizeof(struct WordNode));
        word->word_pos = word_pos;
        word->next = file[file_no - 1].next;
        file[file_no - 1].next = word;
        file[file_no - 1].word_pos++; /* 头结点累计词汇量 */
    }
}

#define Swap(x, y) { int t = x; x = y; y = t; }
double Similarity(WordList file, int f1, int f2, HashTable htable) {
    /* 计算文件f1和f2的相似度 */
    WordList word;
    PostingList pl;
    int cnt;

    if (file[f1 - 1].word_pos > file[f2 - 1].word_pos) { /* 比较词汇量 */
        Swap(f1, f2);
    } /* 保证f1的词汇量较小 */
    cnt = 0; /* 准备统计公共词汇量 */
    word = file[f1 - 1].next; /* word扫描f1的词汇索引表 */
    while (word != NULL) { /* 对f1中的每个单词word */
        /* pl先找到word在散列表中的倒排索引表 */
        pl = htable->ht[word->word_pos]->pl;
        while (pl != NULL) { /* pl扫描word的倒排索引表 */
            if (pl->file_no == f2) {
                break; /* 单词word也在f2里 */
            }
            pl = pl->next;
        }
        if (pl != NULL) { /* 即单词word也在f2里 */
            cnt++; /* 说明word是两个文件公共的单词 */
        }
        word = word->next;
    }
    /* 两文件的词汇总量 = 两文件词汇量的和 - 公共词汇量 */
    return ((double)(cnt * 100.0) / (double)(file[f1 - 1].word_pos + file[f2 -
            1].word_pos - cnt));
}

int main() {
    ElemSet word;
    HashTable htable;
    WordList file;
    int n, m, f1, f2, i;

    scanf("%d\n", &n);
    file = InitFileWordList(n); /* 初始化文件的词汇表 */
    htable = InitHashTable(kMaxTableSize); /* 创建一个散列表 */
    for (i = 0; i < n; i++) { /* 读入并索引每个文件 */
        while (GetWord(word) == true) { /* 从第(i+1)号文件中分词 */
            /* 将单词插入散列表，更新倒排索引表，更新词汇表 */
            InsertWordToFile(file, i + 1, InsertHash(htable, word, i + 1));
        }
    }
    scanf("%d", &m);
    for (i = 0; i < m; i++) { /* 处理每条查询 */
        scanf("%d %d", &f1, &f2);
        printf("%.1f%%\n", Similarity(file, f1, f2, htable));
    }

    return 0;
}